﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections.Specialized;
using System.Runtime.Remoting;
using System.Diagnostics;
using SEAM.Core;
using SEAM.Exception.Formatter;

namespace SEAM.Exception.Publisher
{
    public abstract class ExceptionPublisherBase : IExceptionPublisher
    {
        private bool _enabled = true;
        private int _priority;
        private IExceptionFormatter _format;

        public virtual bool Enabled
        {
            get { return _enabled; }
            set { _enabled = value; }
        }
        public virtual int Priority
        {
            get { return _priority; }
            set { _priority = value; }
        }
        public virtual IExceptionFormatter Format
        {
            get { return _format; }
            set { _format = value; }
        }

        public ExceptionPublisherBase(XmlNode node) 
        {
            string formatterName = GetAttributeValue(node, "format", false);
            Format = GetExceptionFormatter(formatterName);
            int.TryParse(GetAttributeValue(node, "priority", false), out _priority);

        }

        public abstract bool PublishException(System.Exception ex, IDictionary<string, object> additionalInfo);
        public virtual bool PublishException(System.Exception ex)
        {
            return PublishException(ex, null);
        }
        protected virtual IExceptionFormatter GetExceptionFormatter(string format)
        {
            try
            {
                return (IExceptionFormatter)ObjectFactory.CreateObject(format);
            }
            catch (System.Exception ex2)
            {
                Trace.TraceWarning(ex2.Message + Environment.NewLine + ex2.StackTrace);
            }

            return null;
        }

        protected static string GetAttributeValue(XmlNode node, string attributeName, bool isRequired)
        {
            if (node == null || node.Attributes == null || node.Attributes[attributeName] == null || string.IsNullOrEmpty(node.Attributes[attributeName].Value))
            {
                if (isRequired)
                    throw new ArgumentException("Invalid or missing value for " + attributeName, attributeName);
                else
                    return null;
            }
            else
                return node.Attributes[attributeName].Value.ToString();
        }
        protected static string GetFormattedMessage(System.Exception ex, IExceptionFormatter format, ICollection<object> additionalInfo)
        {
            Dictionary<string, object> dictInfo = new Dictionary<string, object>();
            if (additionalInfo != null)
            {
                foreach (object obj in additionalInfo.Where(o => o != null))
                    dictInfo.Add(obj.GetType().FullName, obj);
            }
            return GetFormattedMessage(ex, format, dictInfo);
        }
        protected static string GetFormattedMessage(System.Exception ex, IExceptionFormatter format, IDictionary<string, object> additionalInfo)
        {
            return format.GetFormattedMessage(ex, additionalInfo);
        }
    }
}
